package com.container.app.proxy;

import com.container.app.exceptions.MContainerUncheckedException;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * Created with IntelliJ IDEA.
 * User: Georgiana.Scarlat
 * Date: 7/26/12
 * Time: 11:18 AM
 */

public abstract class ContainerProxyHandler implements InvocationHandler {

    protected Object proxiesObject;

    protected ContainerProxyHandler(Object proxiesObject) {
        this.proxiesObject = proxiesObject;
    }

    public Object newProxyInstance() {

        return Proxy.newProxyInstance(
                proxiesObject.getClass().getClassLoader(),
                proxiesObject.getClass().getInterfaces(),
                this);
    }


    public Object invoke(Object proxy, Method method, Object[] args) {

        Object result;

        method.setAccessible(true);

        result = wrapMethod(method, args);

        return result;

    }

    public Object wrapMethod(Method method, Object[] args) {

        Object result = null;
        beforeMethod(method);
        try {
            result = method.invoke(proxiesObject, args);
        } catch (IllegalAccessException e) {
            throw new MContainerUncheckedException("Can't invoke method " + method.getName() + " because it is not accessible.", e);
        } catch (InvocationTargetException e) {
            throw new MContainerUncheckedException("Method " + method.getName() + " throws an Exception. ", e);
        } finally {
            afterMethod(method);
        }
        return result;


    }

    public abstract void beforeMethod(Method method);

    public abstract void afterMethod(Method method);

    @SuppressWarnings("UnusedDeclaration")
    protected Object getProxiesObject() {
        return proxiesObject;
    }
}
